package test.y2021;

import monad.Try;

import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created By  醉美柳舞之众星捧月
 *
 * @author song
 * @date 2021/11/25 11:14
 */
public interface Aspect {

    /**
     * before
     */
    void before();

    /**
     * after
     */
    void after();

    /**
     * getProxy
     *
     * @param cls     1
     * @param aspects 2
     * @param <T>     3
     * @return 4
     */
    static <T> T getProxy(Class<T> cls, String... aspects) {
        List<Try<Aspect>> collect = Arrays.stream(aspects).map(i -> Try.ofFailable(() -> {
                    Class<?> aClass = Class.forName(i);
                    return (Aspect) aClass.getConstructor().newInstance();
                }
        )).filter(Try::isSuccess).collect(Collectors.toList());
        return (T) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), (proxy, method, args) -> {
                    collect.forEach(i -> {
                        try {
                            i.get().before();
                        } catch (Throwable e) {
                            e.printStackTrace();
                        }
                    });
                    Object invoke = method.invoke(cls.getConstructor().newInstance());
                    collect.forEach(i -> {
                        try {
                            i.get().after();
                        } catch (Throwable e) {
                            e.printStackTrace();
                        }
                    });
                    return invoke;
                }
        );
    }
}
